﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
using DIS.WindowsPhone.Toolkit.Controls.Extensions;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Phone.UserData;

namespace DIS.WindowsPhone.Toolkit.Controls
{
    public partial class ContactPickerPage : PhoneApplicationPage
    {
        private const string StateKey_Value = "ContactPickerPage_State_Value";
        private bool _isGroupingOpened = false;

        public ContactPickerPage()
        {
            InitializeComponent();
            SetAppBar();
            Contacts = new List<Contact>();
            VisualStateManager.GoToState(this, "Normal", false);
        }

        public string HeaderText
        {
            get
            {
                return lblChooseContact.Text;
            }
            set
            {
                lblChooseContact.Text = value;
            }
        }

        public string SearchText
        {
            get
            {
                return ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).Text;
            }
            set
            {
                ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).Text = value;
            }
        }

        private void SetAppBar()
        {
            ApplicationBarIconButton icon = new ApplicationBarIconButton();
            string background = "dark";
            if (Application.Current.Host.Background == Colors.White)
                background = "light";
            icon.IconUri = new System.Uri(string.Format("/Icons/{0}/Search.png", background), System.UriKind.Relative);
            icon.Text = "search";
            icon.Click += new System.EventHandler(iconSearch_Click);
            ApplicationBar.Buttons.Add(icon);
        }

        void iconSearch_Click(object sender, System.EventArgs e)
        {
            contactsLongList.IsFlatList = true;
            contactsLongList.DataContext = null;
            contactsLongList.ClearValue(LongListSelector.DataContextProperty);
            contactsLongList.DataContext = Contacts;
            ApplicationBar.IsVisible = false;
            VisualStateManager.GoToState(this, "Searching", true);
            tbSearch.Focus();
        }

        /// <summary>
        /// Gets or sets the list of items to display.
        /// </summary>
        public List<Contact> Contacts { get; private set; }

        private List<GroupedContacts> _groupedContacts;
        public List<GroupedContacts> GroupedContacts
        {
            get
            {
                if (_groupedContacts == null && Contacts != null)
                    _groupedContacts = GroupContacts(Contacts);

                return _groupedContacts;
            }
        }

        private static List<GroupedContacts> GroupContacts(List<Contact> contacts)
        {

            var contactsByInitial = (from c in contacts
                                     group c by GroupByNumer(Regex.Replace(c.DisplayName, "[()-]", "")[0]) into g
                                     orderby g.Key
                                     select new GroupedContacts(g.Key, g, true)).ToList();

            for (char c = 'a'; c <= 'z'; c++)
            {
                if (!contactsByInitial.Where(x => x.Title == c.ToString()).Any())
                    contactsByInitial.Add(new GroupedContacts(c.ToString(), new List<Contact>(), false));
            }
            if (!contactsByInitial.Where(x => x.Title == "#").Any())
                contactsByInitial.Add(new GroupedContacts("#", new List<Contact>(), false));

            contactsByInitial = contactsByInitial.OrderBy(c => c.Title).ToList();

            return contactsByInitial;
        }

        private static string GroupByNumer(char firstChar)
        {
            //0 - 9
            int charVal = (int)firstChar;
            if (charVal >= 48 && charVal <= 57)
                return "#";

            return firstChar.ToString().ToLower();
        }

        /// <summary>
        /// Gets or sets the selected item.
        /// </summary>
        public Contact SelectedItem { get; set; }

        private void contactsLongList_GroupViewClosing(object sender, GroupViewClosingEventArgs e)
        {
            GroupedContacts gc = e.SelectedGroup as GroupedContacts;
            if (gc != null)
                e.Cancel = gc.Contacts.Count == 0;

            _isGroupingOpened = false;
        }

        private void contactsLongList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            // Commit the value and close
            SelectedItem = contactsLongList.SelectedItem as Contact;
            if (SelectedItem != null) //this gets called when clicking on the group as well! We shouldn't close the picker then!
                ClosePickerPage();
        }

        private void ClosePickerPage()
        {
            // Close the picker page
            NavigationService.GoBack();
        }

        private void tbSearch_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            //DataSource.Search(tbSearch.Text);
            if (String.IsNullOrWhiteSpace(tbSearch.Text))
            {

            }
            var tmpList = Contacts.Where(c => c.DisplayName.StartsWith(tbSearch.Text, StringComparison.InvariantCultureIgnoreCase)).ToList();
            contactsLongList.DataContext = null;
            contactsLongList.ClearValue(LongListSelector.DataContextProperty);
            //reset the list with all contacts again
            contactsLongList.DataContext = tmpList;
        }

        /// <summary>
        /// Called when a page becomes the active page in a frame.
        /// </summary>
        /// <param name="e">An object that contains the event data.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }

            base.OnNavigatedTo(e);

            // Restore Value if returning to application (to avoid inconsistent state)
            if (State.ContainsKey(StateKey_Value))
            {
                State.Remove(StateKey_Value);

                // Back out from picker page for consistency with behavior of core pickers in this scenario
                if (NavigationService.CanGoBack)
                {
                    NavigationService.GoBack();
                    return;
                }
            }

            contactsLongList.DataContext = GroupedContacts;
        }

        /// <summary>
        /// Called when a page is no longer the active page in a frame.
        /// </summary>
        /// <param name="e">An object that contains the event data.</param>
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }

            base.OnNavigatedFrom(e);

            // Save Value if navigating away from application
            if (e.Uri.IsExternalNavigation())
            {
                State[StateKey_Value] = StateKey_Value;
            }
        }

        /// <summary>
        /// Called when the Back key is pressed.
        /// </summary>
        /// <param name="e">Event arguments.</param>
        protected override void OnBackKeyPress(CancelEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }

            if (this.VisualStateGroup.CurrentState.Name == "Searching")
            {
                e.Cancel = true;
                contactsLongList.IsFlatList = false;
                contactsLongList.DataContext = null;
                contactsLongList.ClearValue(LongListSelector.DataContextProperty);
                //reset the list with all contacts again
                contactsLongList.DataContext = GroupedContacts;
                ApplicationBar.IsVisible = true;
                VisualStateManager.GoToState(this, "Normal", true);
            }
            else if (_isGroupingOpened)
            {
                e.Cancel = true; //we don't want to do anything. We have to let the long list do it's magic
            }
            else
            {
                // Cancel back action so we can play the Close state animation (then go back)
                e.Cancel = true;
                SelectedItem = null;
                ClosePickerPage();
            }

        }

        private void contactsLongList_GroupViewOpened(object sender, GroupViewOpenedEventArgs e)
        {
            _isGroupingOpened = true;
        }


    }
}